package util

import (
	"bytes"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"

	"gitee.com/lei_wenbin/mahonia"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

// -----编码处理-start---------------------------------------
// 判断字符串是否是gbk
func IsGBK(data []byte) bool {
	length := len(data)
	var i int = 0
	for i < length {
		if data[i] <= 0xff {
			i++
			continue
		} else {
			if data[i] >= 0x81 &&
				data[i] <= 0xfe &&
				data[i+1] >= 0x40 &&
				data[i+1] <= 0xfe &&
				data[i+1] != 0xf7 {
				i += 2
				continue
			} else {
				return false
			}
		}
	}
	return true
}
func preNUm(data byte) int {
	str := fmt.Sprintf("%b", data)
	var i int = 0
	for i < len(str) {
		if str[i] != '1' {
			break
		}
		i++
	}
	return i
}

// 判断字符串是否是utf-8:
func IsUtf8(data []byte) bool {
	for i := 0; i < len(data); {
		if data[i]&0x80 == 0x00 {
			i++
			continue
		} else if num := preNUm(data[i]); num > 2 {
			i++
			for j := 0; j < num-1; j++ {
				if data[i]&0xc0 != 0x80 {
					return false
				}
				i++
			}
		} else {
			return false
		}
	}
	return true
}

// GBK 转 UTF-8
func GbkToUtf8(s []byte) ([]byte, error) {
	reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
	d, e := io.ReadAll(reader)
	if e != nil {
		return nil, e
	}
	return d, nil
}

// UTF-8 转 GBK
func Utf8ToGbk(s []byte) ([]byte, error) {
	reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
	d, e := io.ReadAll(reader)
	if e != nil {
		return nil, e
	}
	return d, nil
}

// 字符串编码转换
func CodingConversion(waitConversion []byte) string {

	var reConversionBool bool = IsUtf8(waitConversion)
	var utf8Data []byte
	var utf8DataStr string
	var err error
	if reConversionBool == false {
		utf8Data, err = simplifiedchinese.GBK.NewDecoder().Bytes(waitConversion)
		if err == nil {
			utf8DataStr = string(utf8Data)
		}
	}
	return utf8DataStr
}

// 编码转换
func CodeConversion(src string, srcCode string, targetCode string) []byte {
	srcCoder := mahonia.NewDecoder(srcCode)
	srcResult := srcCoder.ConvertString(src)
	tagCoder := mahonia.NewDecoder(targetCode)
	_, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
	return cdata
}

//-----编码处理-end-----------------------------------------

// -----字符串正则-start---------------------------------------
// 正则匹配字符串
func StrMatch(match string, str string, isrr int) string {

	SecuritiesMatchObj := regexp.MustCompile(match)
	if isrr == 0 {
		return SecuritiesMatchObj.FindString(str)
	}
	return ""
}

//-----字符串正则-end-----------------------------------------

// -----字符串处理-start---------------------------------------
// 字符串替换
func StrSingularReplace(str string, oldStr string, newStr string) string {
	return strings.Replace(str, oldStr, newStr, -1)
}

//-----字符串处理-end-----------------------------------------

// -----整型<->字符串-start---------------------------------------

// string转成int
func StrToInt(str string) int {
	var reInt int
	reInt, _ = strconv.Atoi(str)
	return reInt
}

// string转成int64
func StrToInt64(str string) int64 {

	var reInt64 int64
	reInt64, _ = strconv.ParseInt(str, 10, 64)
	return reInt64
}

// string转成float64, 保留小数后几位
func StrToFloat64(str string, num string) float64 {

	var val float64
	val, _ = strconv.ParseFloat(str, 64)
	if num == "0" {
		return val
	}
	var reVal float64
	reVal, _ = strconv.ParseFloat(fmt.Sprintf("%."+num+"f", val), 64)
	return reVal
}

// string转uint8
func StrToUint8(str string) uint8 {
	stint := StrToInt64(str)
	return uint8(stint)
}

// 字符串转Uint
func StrToUint(str string) uint {
	id, _ := strconv.ParseUint(str, 10, 64)
	return uint(id)
}

// 字符串转Uint16
func StrToUint16(str string) uint16 {
	num16, _ := strconv.ParseUint(str, 10, 16)
	return uint16(num16)
}

// 字符串转Uint16
func StrToUint64(str string) uint64 {

	intNum, _ := strconv.Atoi(str)
	return uint64(intNum)
}

// int转成string
func IntToStr(num int) string {

	var str string
	str = strconv.Itoa(num)
	return str
}

func UintToStr(num uint) string {
	var str string
	str = strconv.FormatUint(uint64(num), 10)
	return str
}

// int64转成string：
func Int64ToStr(num int64) string {
	var str string
	str = strconv.FormatInt(num, 10)
	return str
}

// int64转成string：
func Uint64ToStr(num uint64) string {
	var str string
	str = strconv.FormatUint(num, 10)
	return str
}

// float64 转 string
func Float64ToStr(f64 float64, n int) string {
	return strconv.FormatFloat(f64, 'f', n, 64)
}

// float32 转 string
func Float32ToStr(f32 float64) string {
	return strconv.FormatFloat(float64(f32), 'f', 10, 32)
}

//-----整型<->字符串-end-----------------------------------------

// 唯一身份标识
func Identify(str []string) string {
	_, year := YearStr()
	_, month := Month()
	_, day := Day()
	week := WeekStr()
	_, hour := Hour()
	_, min := Min()
	_, second := Second()
	var l = make([]string, 0)
	l = append(l, year)
	l = append(l, month)
	l = append(l, day)
	l = append(l, week)
	l = append(l, hour)
	l = append(l, min)
	l = append(l, second)
	l = append(l, Int64ToStr(Time()))
	l = append(l, Int64ToStr(Milli()))
	l = append(l, Int64ToStr(Micro()))
	l = append(l, Uint64ToStr(Nanosecond()))
	l = append(l, Uint64ToStr(Nanosecond()))
	if len(str) > 0 {
		l = append(l, str...)
	}
	ll := len(l)
	var md5 string
	var k string
	if ll > 0 {
		for i := 0; i < ll; i++ {
			md5 = Md5(md5 + l[i])
			k = k + l[i]
		}
		return md5 + Md5(k) + md5 + Md5(k)
	}
	return Md5(year+month+day+week) + Md5(hour+min+second) + Md5(year+month+day+week) + Md5(hour+min+second)
}
